package com.bcx.wind.workflow.imp.cmd.managercmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.WorkflowOperate;
import com.bcx.wind.workflow.entity.WindActHistory;
import com.bcx.wind.workflow.entity.WindProcess;
import com.bcx.wind.workflow.entity.WindTask;
import com.bcx.wind.workflow.entity.WindTaskActor;
import com.bcx.wind.workflow.interceptor.Command;
import com.bcx.wind.workflow.interceptor.CommandContext;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.JsonHelper;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.LinkedList;
import java.util.List;

import static com.bcx.wind.workflow.message.ErrorCode.LACK_TRANSFER_DATA;

/**
 * 转办任务命令  将一个人的指定的任务集合转办给另一个人，转办完成后，任务将完全有另一个人审批，前者除了历史将和这个任务无任何关系
 *
 * 转办的任务集合参数  可以分为指定任务ID  指定流程实例ID  指定流程定义ID   指定流程定义名称   指定流程定义模块  指定系统标识
 * 按照参数是否为空  以上面的顺序作为优先级顺序，只取一个值作为参数，进行转办操作
 *
 * @author zhanglei
 */
public class TransferCommand implements Command<List<WindTask>> {

    /**
     * 指定的任务ID集合
     */
    private List<String> taskIds;

    /**
     * 指定的流程实例ID 集合 和任务ID是一对多的关系
     */
    private List<String>  orderIds;

    /**
     * 指定流程定义ID集合  和流程实例ID是一对多的关系
     */
    private List<String>  processIds;

    /**
     * 指定流程名称集合  和流程定义ID是一对多的关系
     */
    private List<String>  processNames;

    /**
     * 指定流程定义模块ID  和流程定义名称是一对多的关系
     */
    private List<String>  modules;

    /**
     * 指定系统标识集合  和流程定义模块是一对多的关系
     */
    private List<String>  systems;

    /**
     * 就审批人
     */
    private String oldUserId;

    /**
     * 新审批人
     */
    private WindUser newUser;

    /**
     * 是否已经转办
     */
    private boolean transferred ;


    /**
     * 返回值
     */
    private List<WindTask>  result = new LinkedList<>();

    /**
     * 执行数据
     */
    private CommandContext commandContext;

    /**
     * 当前操作人
     */
    private WindUser user;

    public TransferCommand(List<String> taskIds,
                           List<String> orderIds,
                           List<String> processIds,
                           List<String> processNames,
                           List<String> modules,
                           List<String> systems,
                           String oldUserId,
                           WindUser newUser,
                           WindUser windUser){
        this.taskIds = taskIds;
        this.orderIds = orderIds;
        this.processIds = processIds;
        this.processNames = processNames;
        this.modules = modules;
        this.systems = systems;
        this.oldUserId = oldUserId;
        this.newUser = newUser;
        this.user = windUser;
    }


    @Override
    public List<WindTask> executor(CommandContext context) {
        try{
            this.commandContext = context;
            return execute();
        }catch (Exception e) {
            context.log(e);
            return null;
        }
    }


    private List<WindTask> execute() {
        //校验参数
        checkArgs();
        if(!this.transferred){
            transferTaskId();
        }
        if(!this.transferred){
            transferOrderId();
        }
        if(!this.transferred){
            transferProcessId();
        }
        if(!this.transferred){
            transferProcessName();
        }
        if(!this.transferred){
            transferProcessModule();
        }
        if(!this.transferred){
            transferSystem();
        }
        return this.result;
    }



    private void checkArgs(){
        Assert.isTrueError(LACK_TRANSFER_DATA,ObjectHelper.isEmpty(this.oldUserId)
                   || ObjectHelper.isEmpty(this.newUser) || ObjectHelper.isEmpty(this.newUser.getUserId()));
    }


    /**
     * 转办操作
     * 查看转办任务审批人是否为旧审批人，如果是，则执行转办，不是跳过
     * 执行转办 ： 删除旧任务以及审批人，新建新任务以及审批人，添加审批履历
     *
     */
    private void transferOperate(WindTask windTask){
        String taskId = windTask.getId();
        //任务的审批人
        QueryFilter filter = new QueryFilter()
                .setTaskId(taskId);
        List<WindTaskActor> actors = this.commandContext.access().selectTaskActorList(filter);
        if(!ObjectHelper.isEmpty(actors)){
            //查看旧审批人是否是需要转办任务的审批人
            WindTaskActor windTaskActor = actors.stream().filter(actor->actor.getActorId().equals(this.oldUserId))
                    .findFirst().orElse(null);
            if(windTaskActor == null){
                return;
            }
            //删除任务以及审批人
            this.commandContext.access().removeTaskInstanceById(taskId);
            this.commandContext.access().removeTaskActorByTaskId(taskId);

            //更新历史履历，添加新任务的履历
            WindActHistory actHistory = updateAndInsertHistory(windTask);

            //新增任务以及审批人
            String newTaskId = ObjectHelper.primaryKey();
            windTask.setId(newTaskId);
            windTaskActor.setTaskId(newTaskId)
                    .setActorId(newUser.getUserId());
            this.commandContext.access().insertTaskInstance(windTask);
            this.commandContext.access().insertTaskActor(windTaskActor);
            //添加新的历史履历
            buildNewHistory(actHistory,windTask);
            this.result.add(windTask);
        }
    }


    @SuppressWarnings("unchecked")
    private void buildNewHistory(WindActHistory actHistory,WindTask windTask){
        if(actHistory != null) {
            String approveUserStr = actHistory.getApproveUserVariable();
            List<WindUser> approveUser = JsonHelper.parseJson(approveUserStr,List.class,WindUser.class);
            approveUser.removeIf(u->u.getUserId().equals(oldUserId));
            approveUser.add(this.newUser);
            actHistory.setId(ObjectHelper.primaryKey())
                    .setTaskId(windTask.getId())
                    .setOperate(null)
                    .setSubmitUserVariable(null)
                    .setActorId(null)
                    .setActorName(null)
                    .setSuggest(null)
                    .setApproveTime(null)
                    .setApproveUserVariable(JsonHelper.toJson(approveUser));
            this.commandContext.access().insertActiveHistory(actHistory);
        }
    }


    /**
     * 更新历史履历
     *
     * @param windTask  任务实例
     */
    private WindActHistory updateAndInsertHistory(WindTask windTask){
        QueryFilter filter = new QueryFilter()
                .setTaskId(windTask.getId());
        List<WindActHistory> actHistories = this.commandContext.access().selectActiveHistoryList(filter);
        if(!ObjectHelper.isEmpty(actHistories)){
            WindActHistory history = actHistories.get(0);
            history.setSubmitUserVariable(JsonHelper.toJson(user()))
                    .setOperate(WorkflowOperate.transfer.name())
                    .setSuggest(user().getUserId()+" transfer task "+windTask.getId()+" success "+oldUserId+" -----> "+newUser.getUserId())
                    .setApproveTime(TimeHelper.nowDate())
                    .setActorId(user().getUserId())
                    .setActorName(user().getUserName());
            this.commandContext.access().updateActiveHistory(history);
            return history;
        }
        return null;
    }


    /**
     * 通过任务转办
     */
    private void transferTaskId(){
        if(!ObjectHelper.isEmpty(this.taskIds)){
            this.transferred = true;
            QueryFilter filter = new QueryFilter()
                     .setTaskIds(this.taskIds.toArray(new String[]{}));
            List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);
            for(WindTask windTask : windTasks){
                transferOperate(windTask);
            }
        }
    }


    /**
     * 通过流程实例ID转办
     */
    private void transferOrderId(){
        if(!ObjectHelper.isEmpty(this.orderIds)){
            this.transferred = true;

            QueryFilter filter = new QueryFilter()
                    .setOrderIds(orderIds.toArray(new String[]{}));
            List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);

            for(WindTask windTask : windTasks){
                transferOperate(windTask);
            }
        }
    }


    /**
     * 通过流程定义ID转办
     */
    private void transferProcessId(){

        if(!ObjectHelper.isEmpty(this.processIds)){
            this.transferred = true;

            for(String processId : this.processIds){
                QueryFilter filter = new QueryFilter()
                        .setProcessId(processId);
                List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);

                for(WindTask windTask : windTasks){
                    transferOperate(windTask);
                }
            }
        }

    }


    /**
     * 通过流程定义名称进行转办
     */
    private void transferProcessName(){

        if(!ObjectHelper.isEmpty(this.processNames)){
            this.transferred = true;

            for(String processName : this.processNames){
                QueryFilter filter = new QueryFilter()
                        .setProcessName(processName);
                List<WindProcess> windProcesses = this.commandContext.access().selectProcessList(filter);
                transferByWindProcess(windProcesses);
            }
        }
    }

    /**
     * 通过流程定义模块转办
     */
    private void transferProcessModule(){

        if(!ObjectHelper.isEmpty(this.modules)){
            this.transferred = true;

            for(String processModule : modules){

                QueryFilter filter = new QueryFilter()
                        .setProcessModule(processModule);
                List<WindProcess> windProcesses = this.commandContext.access().selectProcessList(filter);
                transferByWindProcess(windProcesses);
            }
        }
    }



    private void transferByWindProcess(List<WindProcess> windProcesses){
        for(WindProcess windProcess : windProcesses){
            QueryFilter processIdFilter = new QueryFilter()
                    .setProcessId(windProcess.getId());
            List<WindTask>  windTasks = this.commandContext.access().selectTaskInstanceList(processIdFilter);

            for(WindTask windTask : windTasks){
                transferOperate(windTask);
            }
        }
    }



    /**
     * 通过系统标识转办
     */
    private void transferSystem(){

        if(!ObjectHelper.isEmpty(this.systems)){
            this.transferred = true;

            for(String system : this.systems){
                QueryFilter filter = new QueryFilter()
                        .setSystem(system);
                List<WindProcess> windProcesses = this.commandContext.access().selectProcessList(filter);
                transferByWindProcess(windProcesses);
            }
        }

    }


    private WindUser user(){
        return this.user == null ? new WindUser()
                .setUserId("admin")
                .setUserName("管理员") : this.user;
    }


}
